package com.cgnpc.scp.purchase.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cgnpc.cud.core.domain.AjaxResult;
import com.cgnpc.cuddemo.utils.IDHelper;
import com.cgnpc.scp.common.bean.CreateFileInfo;
import com.cgnpc.scp.common.bean.MyPageResult;
import com.cgnpc.scp.common.pojo.UserInfo;
import com.cgnpc.scp.common.service.AppConstantService;
import com.cgnpc.scp.common.service.ExcelCustomTemplateService;
import com.cgnpc.scp.common.utils.*;
import com.cgnpc.scp.purchase.mybatis.entity.PurchaseProject;
import com.cgnpc.scp.purchase.mybatis.entity.PurchaseProjectExampleExtend;
import com.cgnpc.scp.purchase.mybatis.mapper.client.PurchaseProjectMapper;
import com.cgnpc.scp.purchase.service.IPurchaseProjectService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.*;

@Service
public class PurchaseProjectServiceImpl implements IPurchaseProjectService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PurchaseProjectServiceImpl.class);

    @Autowired
    private PurchaseProjectMapper purchaseProjectMapper;

    @Autowired
    private SqlSession sqlSession;

    @Autowired
    private AppConstantService appConstantService;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private ExcelCustomTemplateService excelCustomTemplateService;

    @Override
    public <T extends PurchaseProject> MyPageResult<T> loadByPaging(T reqEntity) {
        // begin 分页查询
        // 第几页
        int pageNum = reqEntity.getPageNum();
        // 每页的数量
        int pageSize = reqEntity.getPageSize();
        // 创建Page对象，将pageNum，pageSize参数传入，必须位于数据库查询数据的语句之前，否则不生效
        com.github.pagehelper.Page<T> queryPage = PageHelper.startPage(pageNum, pageSize);

        // 创建queryExample
        PurchaseProjectExampleExtend queryExample = createQueryExample(reqEntity);

        purchaseProjectMapper.selectByExampleWithCustom(queryExample);

        // pagehelper分页插件的问题，需要创建PageInfo才能获取总记录数，queryPage.getResult()和dbEntityList是一样的
        PageInfo<T> pageResult = new PageInfo<>(queryPage.getResult());

        // 创建分页结果集对象
        MyPageResult<T> myPageResult = MyPageResultUtil.createMyPageResult(pageResult);
        // end 分页查询

        return myPageResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends PurchaseProject> AjaxResult saveOrUpdate(UserInfo loginUserInfo, Locale reqLocale, List<T> reqEntityList) {
        final String logInfo = "[PurchaseProject_saveOrUpdate_UUID_" + UUID.randomUUID() + "]";
        AjaxResult ajaxResult = null;

        try {
            Date nowDate = new Date();

            // begin 获取登录用户的信息
            String loginUserInfoUserId = loginUserInfo.getUserId();
            String loginUserInfoUserName = loginUserInfo.getUserName();
            // end 获取登录用户的信息

            PurchaseProject dbPurchaseProject = null;
            PurchaseProject usedEntity = null;
            int saveRows = 0;
            int updateRows = 0;

            String reqId = null;
            String reqProjectCode = null;

            for (PurchaseProject reqEntity : reqEntityList) {
                reqId = reqEntity.getId();
                reqProjectCode = reqEntity.getProjectCode();

                // dbPurchaseProject = purchaseProjectMapper.selectByPrimaryKey(reqId);

                if (StringUtil.isNullOrSpace(reqId)) {
                    // 保存
                    usedEntity = new PurchaseProject();
                    usedEntity.setId(IDHelper.uuidNew());
                    usedEntity.setProjectCode(reqProjectCode);
                    usedEntity.setProjectName(reqEntity.getProjectName());
                    usedEntity.setDescription(reqEntity.getDescription());
                    usedEntity.setIsValid(reqEntity.getIsValid());
                    usedEntity.setCreateTime(nowDate);
                    usedEntity.setCreateUser(loginUserInfoUserId);
                    usedEntity.setCreateUserName(loginUserInfoUserName);
                    usedEntity.setLastUpdateTime(nowDate);
                    usedEntity.setLastUpdateUser(loginUserInfoUserId);
                    usedEntity.setLastUpdateUserName(loginUserInfoUserName);

                    saveRows += purchaseProjectMapper.insert(usedEntity);
                } else {
                    // 修改
                    usedEntity = new PurchaseProject();
                    usedEntity.setId(reqId);
                    usedEntity.setProjectCode(reqProjectCode);
                    usedEntity.setProjectName(reqEntity.getProjectName());
                    usedEntity.setDescription(reqEntity.getDescription());
                    usedEntity.setIsValid(reqEntity.getIsValid());
                    // usedEntity.setCreateTime(nowDate);
                    // usedEntity.setCreateUser(loginUserInfoUserId);
                    // usedEntity.setCreateUserName(loginUserInfoUserName);
                    usedEntity.setLastUpdateTime(nowDate);
                    usedEntity.setLastUpdateUser(loginUserInfoUserId);
                    usedEntity.setLastUpdateUserName(loginUserInfoUserName);

                    updateRows += purchaseProjectMapper.updateById(usedEntity);
                }
            }

            String strResultInfo = "保存" + saveRows + "行；修改" + updateRows + "行；";

            ajaxResult = AjaxResultUtil.createSuccessMessage(strResultInfo);
        } catch (Exception e) {
            LOGGER.error("{}saveOrUpdate.error;", logInfo, e);
            throw e;
        }

        return ajaxResult;
    }

    /**
     * 创建查询Example
     *
     * @param reqEntity reqEntity
     * @param <T>       T
     * @return Example
     */
    private <T extends PurchaseProject> PurchaseProjectExampleExtend createQueryExample(T reqEntity) {
        // mybatis查询方式
        PurchaseProjectExampleExtend queryExample = new PurchaseProjectExampleExtend();

        // 设置排序字段
        // queryExample.setOrderByClause("order_index");

        // 设置查询条件

        // 项目代码
        if (!StringUtil.isNullOrSpace(reqEntity.getProjectCode())) {
            // queryExampleCriteria.andProjectCodeLike(SqlUtil.valueJoinLikeBoth(reqEntity.getProjectCode()));
            // addCriterion("project_code like", value, "projectCode");
            queryExample.setProjectCodeLike(SqlUtil.valueJoinLikeBoth(reqEntity.getProjectCode()));
        }

        // 项目名称
        if (!StringUtil.isNullOrSpace(reqEntity.getProjectName())) {
            // queryExampleCriteria.andProjectNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getProjectName()));
            // addCriterion("project_name like", value, "projectName");
            queryExample.setProjectNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getProjectName()));
        }
        // 勾选项目----多个id
        if (ListUtil.getListSizeWith0(reqEntity.getIds()) > 0) {
            // queryExampleCriteria.andProjectNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getProjectName()));
            // addCriterion("project_name like", value, "projectName");
            queryExample.setIds(reqEntity.getIds());
        }
        return queryExample;
    }

    @Override
    public <T extends PurchaseProject> CreateFileInfo exportExcel(T reqEntity) throws Exception {
        final String logInfo = "[exportExcel_UUID_" + UUID.randomUUID() + "]";
        CreateFileInfo createFileInfo = null;

        try {
            // 创建queryExample
            PurchaseProjectExampleExtend queryExample = createQueryExample(reqEntity);

            // mappedStatementNamespace为mybatis生成的mapper.xml中的命名空间
            String mappedStatementNamespace = "com.cgnpc.scp.purchase.mybatis.mapper.client.PurchaseProjectMapper";
            // mappedStatementMethod为mybatis生成的mapper.xml中的方法
            String mappedStatementMethod = "selectByExampleWithCustom";
            // mappedStatementId为具体指向的方法
            String mappedStatementId = mappedStatementNamespace + "." + mappedStatementMethod;

            // mappedStatementParameter可以为mybatis自动生成的XxxExample实体类，例如UserExample
            Object mappedStatementParameter = queryExample;
            String exportDictGroupKey = DataDictUtil.DICT_GROUP_KEY_WITH_PURCHASEPROJECT_EXPORTEXCEL;

            createFileInfo = excelCustomTemplateService.createXlsxToWebDir(
                    sqlSession
                    , mappedStatementId
                    , mappedStatementParameter
                    , exportDictGroupKey
            );
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }

        return createFileInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public <T extends PurchaseProject> AjaxResult importFromExcel(UserInfo loginUserInfo, Locale reqLocale, MultipartFile reqFile) throws Exception {
        final String logInfo = "[importFromExcel_UUID_" + UUID.randomUUID() + "]";
        AjaxResult ajaxResult = null;
        XSSFWorkbook workbook = null;
        InputStream reqFileInputStream = null;

        try {
            if (reqFile == null) {
                return AjaxResultUtil.createErrorMessage("文件不存在");
            }

            boolean reqFileEmpty = reqFile.isEmpty();
            String reqFileName = reqFile.getName();
            String reqFileOriginalFilename = reqFile.getOriginalFilename();

            LOGGER.info("{}reqFileEmpty:{};reqFileName:{};reqFileOriginalFilename:{};"
                    , logInfo
                    , reqFileEmpty, reqFileName, reqFileOriginalFilename
            );

            if (!reqFileOriginalFilename.toLowerCase().endsWith(".xlsx".toLowerCase(Locale.ENGLISH))) {
                LOGGER.error("{}只支持.xlsx文件。", logInfo);
                return AjaxResultUtil.createErrorMessage("只支持.xlsx文件", null);
            }

            reqFileInputStream = reqFile.getInputStream();
            workbook = new XSSFWorkbook(reqFileInputStream);
            Sheet sheet = workbook.getSheetAt(0);

            Iterator<Row> itRow = sheet.rowIterator();
            int rowIndex = 0;
            Row row = null;
            Cell cell000 = null;
            Cell cell001 = null;
            Cell cell002 = null;
            Cell cell003 = null;
            String cellValue000 = null;
            String cellValue001 = null;
            String cellValue002 = null;
            String cellValue003 = null;

            final List<T> reqEntityList = new ArrayList<>();
            T reqEntity = null;

            while (itRow.hasNext()) {
                row = itRow.next();

                // 第1行为标题
                if (rowIndex++ <= 0) {
                    continue;
                }

                // 项目代码
                // 项目名称
                // 是否有效
                // 项目说明
                cell000 = row.getCell(0);
                cell001 = row.getCell(1);
                cell002 = row.getCell(2);
                cell003 = row.getCell(3);

                cellValue000 = ExcelUtil.getCellValue(cell000);
                cellValue001 = ExcelUtil.getCellValue(cell001);
                cellValue002 = ExcelUtil.getCellValue(cell002);
                cellValue003 = ExcelUtil.getCellValue(cell003);

                reqEntity = (T) new PurchaseProject();
                reqEntityList.add(reqEntity);

                // project_code 项目编码
                reqEntity.setProjectCode(cellValue000);
                // project_name 项目名称
                reqEntity.setProjectName(cellValue001);
                // is_valid 是否有效；值Y有效；N无效；默认Y；
                reqEntity.setIsValid(cellValue002);
                // description 说明
                reqEntity.setDescription(cellValue003);

                if (ListUtil.getListSizeWith0(reqEntityList) >= SqlUtil.INSERT_BATCH_MAX_ROWS) {
                    saveOrUpdate(loginUserInfo, reqLocale, reqEntityList);
                    reqEntityList.clear();
                }
            }

            if (ListUtil.getListSizeWith0(reqEntityList) > 0) {
                saveOrUpdate(loginUserInfo, reqLocale, reqEntityList);
                reqEntityList.clear();
            }

            ajaxResult = AjaxResultUtil.createSuccessMessage("保存成功");
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        } finally {
            IOUtil.closeStream(reqFileInputStream);
            ExcelUtil.closeWorkbook(workbook);
        }

        return ajaxResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends PurchaseProject> AjaxResult del(UserInfo loginUserInfo, Locale reqLocale, T reqEntity) {
        final String logInfo = "[del_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            List<String> reqIds = reqEntity.getIds();

            LOGGER.info("{}printInfo;reqIds:{};"
                    , logInfo
                    , reqIds
            );

            if (ListUtil.getListSizeWith0(reqIds) <= 0) {
                return AjaxResultUtil.createSuccessMessage("请求参数不正确");
            }

            int delRows = purchaseProjectMapper.deleteBatchIds(reqIds);
            LOGGER.info("{}delRows:{};", logInfo, delRows);

            return AjaxResultUtil.createSuccessMessage("删除成功，共删除" + delRows + "行记录。");
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }
    }

    @Override
    public <T extends PurchaseProject> T loadById(String id) {
        if (StringUtil.isNullOrSpace(id)) {
            return null;
        }

        return (T) purchaseProjectMapper.selectById(id);
    }

    @Override
    public <T extends PurchaseProject> List<T> loadByProjectCode(String projectCode) {
        if (StringUtil.isNullOrSpace(projectCode)) {
            return null;
        }

        QueryWrapper<PurchaseProject> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("project_code", projectCode);

        return (List<T>) purchaseProjectMapper.selectList(queryWrapper);
    }

}
